package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.dto.FormDataAddGetDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddGetVO;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.FormUtil;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PayPlanErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainBatchLinkItemDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.product.pojo.vo.RelativeProductExplainVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.OptionTableHeadEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.SubOptionTableHeadEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.OtherExpenseEnum;
import com.xbongbong.saas.enums.business.OtherIncomeEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.PaymentTaskEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.dictionary.PayPlanStatusEnum;
import com.xbongbong.saas.enums.dictionary.PaymentStatusEnum;
import com.xbongbong.saas.model.BomBillModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.service.AssembleService;
import com.xbongbong.saas.service.ClueService;
import com.xbongbong.saas.service.CommunicatePlanService;
import com.xbongbong.saas.service.ContractService;
import com.xbongbong.saas.service.CreditFixedLimitService;
import com.xbongbong.saas.service.CreditTemporaryLimitService;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.CustomerService;
import com.xbongbong.saas.service.InventoryService;
import com.xbongbong.saas.service.InvoiceService;
import com.xbongbong.saas.service.OpportunityService;
import com.xbongbong.saas.service.OtherExpenseService;
import com.xbongbong.saas.service.OtherIncomeService;
import com.xbongbong.saas.service.PayPlanSheetService;
import com.xbongbong.saas.service.PaymentSheetService;
import com.xbongbong.saas.service.PaymentTaskService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductionOrderService;
import com.xbongbong.saas.service.PurchaseInvoiceService;
import com.xbongbong.saas.service.QuotationService;
import com.xbongbong.saas.service.RefundService;
import com.xbongbong.saas.service.ReturnedPurchaseService;
import com.xbongbong.saas.service.SupplierCommunicateService;
import com.xbongbong.saas.service.TransferService;
import com.xbongbong.saas.service.WorkOrderService;
import com.xbongbong.saas.service.WorkReportService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;

/**
 * @author feng.zheng
 * @version v1.0
 * @date 2019/2/12 15:22
 * @since v1.0
 */
@Component
public class SaasAddHelp {

    private static final Logger LOG = LoggerFactory.getLogger(SaasAddHelp.class);

    @Resource
    @Lazy
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private SupplierCommunicateService supplierCommunicateService;
    @Resource
    private OpportunityService opportunityService;
    @Resource
    private WorkReportService workReportService;
    @Resource
    private BomBillModel bomBillModel;
    @Resource
    private ProductService productService;
    @Resource
    private CommunicatePlanService communicatePlanService;
    @Resource
    private ContractService contractService;
    @Resource
    private CustomerService customerService;
    @Resource
    private ProductionOrderService productionOrderService;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private TransferService transferService;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ReturnedPurchaseService returnedPurchaseService;
    @Resource
    private AssembleService assembleService;
    @Resource
    private InstockModel instockModel;
    @Resource
    private PaymentSheetService paymentSheetService;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private InvoiceService invoiceService;
    @Resource
    private RefundService refundService;
    @Resource
    private PaasAppService paasAppService;
    @Resource
    private QuotationService quotationService;
    @Resource
    private DefaultAttrHelp defaultAttrHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ShowFormatHelp showFormatHelp;
    @Resource
    private PayPlanSheetService payPlanSheetService;
    @Resource
    private PurchaseInvoiceService purchaseInvoiceService;
    @Resource
    private ClueService clueService;
    @Resource
    private CreditTemporaryLimitService creditTemporaryLimitService;
    @Resource
    private CreditFixedLimitService creditFixedLimitService;
    @Resource
    private PaymentTaskService paymentTaskService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private OtherIncomeService otherIncomeService;
    @Resource
    private OtherExpenseService otherExpenseService;
    @Resource
    private SaasOtherIncomeHelp saasOtherIncomeHelp;
    @Resource
    private SaasOtherExpenseHelp saasOtherExpenseHelp;

    /**
     * saas新建时给解释字段赋初始值,格式化
     *
     * @param formatExplainDTO 表单解释格式化入参
     * @throws XbbException 抛出业务异常
     * @author feng.zheng
     */
    public void formatExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        Integer businessType = formatExplainDTO.getBusinessType();
        if (businessType == null || businessType == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        boolean needSource = true;
        switch (redundantTemplateTypeEnum) {
            case CUSTOMER:
                customerService.formatAddExplain(formatExplainDTO);
                break;
            case COMMUNICATE:
                customerCommunicateService.formatAddExplain(formatExplainDTO);
                break;
            case JXC_COMMUNICATE:
                supplierCommunicateService.formatAddExplain(formatExplainDTO);
                break;
            case SALES_OPPORTUNITY:
                opportunityService.formatAddExplain(formatExplainDTO);
                break;
            case WORKREPORT:
            case WORKREPORT_DAILY:
            case WORKREPORT_WEEKLY:
            case WORKREPORT_MONTHLY:
                workReportService.formatAddExplain(formatExplainDTO);
                break;
            case BOMBILL:
                bomBillModel.formatAddExplain(formatExplainDTO);
                break;
            case PRODUCT:
                productService.formatAddExplain(formatExplainDTO);
               // productService.formatAddWarehouseToExplain(formatExplainDTO);
                break;
            case COMMUNICATE_PLAN:
                communicatePlanService.formatAddExplain(formatExplainDTO);
                break;
            case CONTRACT:
                contractService.formatAddExplain(formatExplainDTO);
                break;
            case QUOTATION:
                quotationService.formatAddExplain(formatExplainDTO);
                break;
            case REFUND:
                refundService.formatAddExplain(formatExplainDTO);
                break;
            case PRODUCTIONORDER:
                productionOrderService.formatAddExplain(formatExplainDTO);
                break;
            case SUPPLIER:
                supplierModel.formatAddExplain(formatExplainDTO);
                break;
            case PURCHASE:
                purchaseModel.formatAddExplain(formatExplainDTO);
                break;
            case INVENTORY:
                inventoryService.formatAddExplain(formatExplainDTO);
                break;
            case TRANSFER:
                transferService.formatAddExplain(formatExplainDTO);
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
                needSource = outstockModel.formatAddExplain(formatExplainDTO);
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
                needSource = instockModel.formatAddExplain(formatExplainDTO);
                break;
            case RETURNED_PURCHASE:
                returnedPurchaseService.formatAddExplain(formatExplainDTO);
                break;
            case ASSEMBLE:
                assembleService.formatAddExplain(formatExplainDTO);
                break;
            case PAYMENT_SHEET:
                paymentSheetService.formatAddExplain(formatExplainDTO);
                break;
            case PAY_SHEET:
                payPlanSheetService.formatAddExplain(formatExplainDTO);
                break;
            case INVOICE:
                invoiceService.formatAddExplain(formatExplainDTO);
                break;
            case PURCHASE_INVOICE:
                purchaseInvoiceService.formatAddExplain(formatExplainDTO);
                break;
            case WORKORDER:
                workOrderService.formatAddExplain(formatExplainDTO);
                break;
            case CLUE:
                clueService.formatAddExplain(formatExplainDTO);
                break;
//            case MARKET_ACTIVITY:
//                marketActivityService.fo
            case CREDIT_TEMPORARY_LIMIT:
                creditTemporaryLimitService.formatAddExplain(formatExplainDTO);
                break;
            case CREDIT_FIXED_LIMIT:
                creditFixedLimitService.formatAddExplain(formatExplainDTO);
                break;
            default:
                break;
        }
        if (needSource){
            for (FieldAttrEntity item : formatExplainDTO.getExplainList()) {
                if (Objects.equals(item.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType())) {
                    List<FieldAttrEntity> subFormItemArray = (List<FieldAttrEntity>) item.getSubForm().getItems();
                    int linkProductItemIndex = 0;
                    for (int i = 0; i < subFormItemArray.size(); i++) {
                        FieldAttrEntity itemObj = subFormItemArray.get(i);
                        if (Objects.equals(itemObj.getAttr(), "text_1")) {
                            linkProductItemIndex = i;
                            break;
                        }
                    }
                    FieldAttrEntity fieldAttrEntity = subFormItemArray.get(linkProductItemIndex);
                    List<LinkedAttrPoJo> linkedAttrPoJos = fieldAttrEntity.getLinkInfo().getLinkedAttr();
                    formatExplainDTO.setProductField(item);
                    defaultAttrHelp.addProductLinkAttr(XbbRefTypeEnum.getByCode(businessType), linkedAttrPoJos, formatExplainDTO);
                    subFormItemArray.set(linkProductItemIndex, fieldAttrEntity);
                    item.getSubForm().setItems(subFormItemArray);
                }
            }
        }
    }

    /**
     * 合并回/付款时，新建时格式化处理 批量
     * @param xbbRefTypeEnum 业务类型 回款单or付款单
     * @param handlerExplainBatchLinkItemDTO 入参
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void formatSheetBatchLinkAddExplain(XbbRefTypeEnum xbbRefTypeEnum, HandlerExplainBatchLinkItemDTO handlerExplainBatchLinkItemDTO) throws XbbException {
        List<PaasFormDataEntityExt> paasFormDataEntityExts = handlerExplainBatchLinkItemDTO.getPaasFormDataEntityExts();
        Integer linkBusinessType = handlerExplainBatchLinkItemDTO.getLinkBusinessType();
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(linkBusinessType);
        verifySheetData(redundantTemplateTypeEnum, paasFormDataEntityExts);
        List<FieldAttrEntity> explainList = handlerExplainBatchLinkItemDTO.getExplainList();
        FieldAttrEntity timeField = new FieldAttrEntity();
        FieldAttrEntity customerField = new FieldAttrEntity();
        FieldAttrEntity contractField = new FieldAttrEntity();
        FieldAttrEntity paymentField = new FieldAttrEntity();
        switch (xbbRefTypeEnum) {
            case PAY_SHEET:
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.REAL_PAY_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_SUPPLIER.getAttr())) {
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_PURCHASE.getAttr())) {
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.PAY_PLAN.getAttr())) {
                        paymentField = fieldAttrEntity;
                    }
                }
                break;
            default:
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CUSTOMER_ID.getAttr())) {
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CONTRACT.getAttr())) {
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT.getAttr())) {
                        paymentField = fieldAttrEntity;
                    }
                }
                break;
        }
        JSONArray customerArr = new JSONArray();
        List<Long> customerIds = new ArrayList<>();
        JSONArray contractArr = new JSONArray();
        List<Long> contractIds = new ArrayList<>();
        JSONArray paymentArr = new JSONArray();
        switch (redundantTemplateTypeEnum) {
            case PAYMENT:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts){
                    JSONObject linkFormData = paasFormDataEntityExt.getData();
                    formatSheetLink(contractArr, contractIds, linkFormData, PaymentEnum.CONTRACT.getAttr());
                    formatSheetLink(customerArr, customerIds, linkFormData, PaymentEnum.CUSTOMER.getAttr());
                    JSONObject paymentObj = new JSONObject();
                    paymentObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, paasFormDataEntityExt.getId());
                    paymentObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, paasFormDataEntityExt.getSerialNo());
                    paymentArr.add(paymentObj);
                }
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerArr));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
                paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(paymentArr));
                break;
            case CONTRACT:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts){
                    JSONObject linkFormData = paasFormDataEntityExt.getData();
                    formatSheetLink(customerArr, customerIds, linkFormData, ContractEnum.LINK_CUSTOMER.getAttr());
                    JSONObject contractObj = new JSONObject();
                    contractObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, paasFormDataEntityExt.getId());
                    contractObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, paasFormDataEntityExt.getSerialNo());
                    contractArr.add(contractObj);
                }
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerArr));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
                break;
            case PAY_PLAN:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts){
                    JSONObject linkFormData = paasFormDataEntityExt.getData();
                    formatSheetLink(contractArr, contractIds, linkFormData, PayPlanEnum.LINK_PURCHASE.getAttr());
                    formatSheetLink(customerArr, customerIds, linkFormData, PayPlanEnum.LINK_SUPPLIER.getAttr());
                    JSONObject paymentObj = new JSONObject();
                    paymentObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, paasFormDataEntityExt.getId());
                    paymentObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, paasFormDataEntityExt.getSerialNo());
                    paymentArr.add(paymentObj);
                }
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerArr));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
                paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(paymentArr));
                break;
            case PURCHASE:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts){
                    JSONObject linkFormData = paasFormDataEntityExt.getData();
                    formatSheetLink(customerArr, customerIds, linkFormData, PurchaseEnum.SUPPLIER_ID.getAttr());
                    JSONObject contractObj = new JSONObject();
                    contractObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, paasFormDataEntityExt.getId());
                    contractObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, paasFormDataEntityExt.getSerialNo());
                    contractArr.add(contractObj);
                }
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerArr));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
                break;
            default:
                throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
        // 日期
        DefaultAttrPoJo timeDefaultAttrPoJo = timeField.getDefaultAttr();
        if (Objects.isNull(timeDefaultAttrPoJo)) {
            timeDefaultAttrPoJo = new DefaultAttrPoJo();
        }
        timeDefaultAttrPoJo.setDefaultType("dateByBackEnd");
        timeDefaultAttrPoJo.setDefaultValue(DateTimeUtil.getInt() + "");
        timeField.setDefaultAttr(timeDefaultAttrPoJo);
    }

    /**
     * 回/付款单关联新建时格式化解释
     * @param xbbRefTypeEnum 业务类型 回款单or付款单
     * @param handlerExplainInLinkItemDTO 入参
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void formatSheetLinkAddExplain(XbbRefTypeEnum xbbRefTypeEnum, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        JSONObject linkFormData = JsonHelperUtil.getJSONObject(handlerExplainInLinkItemDTO.getLinkFormData());
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        FieldAttrEntity timeField = new FieldAttrEntity();
        FieldAttrEntity customerField = new FieldAttrEntity();
        FieldAttrEntity contractField = new FieldAttrEntity();
        FieldAttrEntity paymentField = new FieldAttrEntity();
        FieldAttrEntity taskField = new FieldAttrEntity();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        switch (xbbRefTypeEnum) {
            case PAY_SHEET:
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.REAL_PAY_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_SUPPLIER.getAttr())) {
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_PURCHASE.getAttr())) {
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.PAY_PLAN.getAttr())) {
                        paymentField = fieldAttrEntity;
                    }
                }
                break;
            default:
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CUSTOMER_ID.getAttr())) {
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CONTRACT.getAttr())) {
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT.getAttr())) {
                        paymentField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TASK.getAttr())) {
                        taskField = fieldAttrEntity;
                    }
                }
                break;
        }
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
        Double unAmount;
        switch (redundantTemplateTypeEnum) {
            case PAYMENT:
                unAmount = linkFormData.getDouble(PaymentEnum.UN_AMOUNT.getAttr());
                if (unAmount == null || unAmount == 0) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_PAYMENT_SHEET_AMOUNT, XbbRefTypeEnum.PAYMENT.getName());
                }
                String paymentStatus = FastJsonHelper.getStringFromFormData(linkFormData, PaymentEnum.STATUS.getAttr());
                if (PaymentStatusEnum.noMerge(paymentStatus)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PAYMENT_BAD_STATUS);
                }
                JSONArray customer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentEnum.CUSTOMER.getAttr(), new JSONArray());
                JSONArray contractArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentEnum.CONTRACT.getAttr(), new JSONArray());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customer));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
                paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
                break;
            case CUSTOMER:
                String customerName = linkFormData.getString(CustomerManagementEnum.NAME.getAttr());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, customerName));
                break;
            case CONTRACT:
                unAmount = getDoubleFromFormData(linkFormData, ContractEnum.UN_FINISH_AMOUNT.getAttr());
                if (unAmount == null || unAmount == 0) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_PAYMENT_SHEET_AMOUNT, I18nMessageUtil.getMessage(CommonConstant.CONTRACT));
                }
                JSONArray contractCustomer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, ContractEnum.LINK_CUSTOMER.getAttr(), new JSONArray());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractCustomer));
                String contractId = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo();
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, contractId));
                break;
            case PAYMENT_TASK:
                boolean paymentTaskTag = false;
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    //需要判断回款单中有没有关联回款计划
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TASK.getAttr()) && BasicConstant.ONE.equals(fieldAttrEntity.getIsOpen())) {
                        paymentTaskTag = true;
                        break;
                    }
                }
                if (!paymentTaskTag) {
                    throw new XbbException(PayPlanErrorCodeEnum.API_ERROR_247007);
                }
                JSONArray taskCustomer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentTaskEnum.LINK_CUSTOMER.getAttr(), new JSONArray());
                JSONArray taskContractArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentTaskEnum.LINK_CONTRACT.getAttr(), new JSONArray());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(taskCustomer));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(taskContractArr));
                taskField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
                break;
            case PAY_PLAN:
                unAmount = getDoubleFromFormData(linkFormData, PayPlanEnum.UN_AMOUNT.getAttr());
                if (unAmount == null || unAmount == 0) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_PAY_SHEET_AMOUNT, XbbRefTypeEnum.PAY_PLAN.getName());
                }
                JSONArray supplier = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PayPlanEnum.LINK_SUPPLIER.getAttr(), new JSONArray());
                JSONArray purchaseArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PayPlanEnum.LINK_PURCHASE.getAttr(), new JSONArray());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(supplier));
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(purchaseArr));
                paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
                break;
            case SUPPLIER:
                String purchaseName = linkFormData.getString(SupplierEnum.SUPPLIER_NAME.getAttr());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, purchaseName));
                break;
            case PURCHASE:
                unAmount = getDoubleFromFormData(linkFormData, PurchaseEnum.UN_FINISH_AMOUNT.getAttr());
                if (unAmount == null || unAmount == 0) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_PAY_SHEET_AMOUNT, XbbRefTypeEnum.PURCHASE.getName());
                }
                JSONArray purchaseSupplier = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray());
                customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(purchaseSupplier));
                String purchaseNo = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo();
                contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, purchaseNo));
                break;
            default:
                throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
        // 日期
        DefaultAttrPoJo timeDefaultAttrPoJo = timeField.getDefaultAttr();
        if (Objects.isNull(timeDefaultAttrPoJo)) {
            timeDefaultAttrPoJo = new DefaultAttrPoJo();
        }
        if (StringUtil.isEmpty(timeDefaultAttrPoJo.getDefaultType())){
            timeDefaultAttrPoJo.setDefaultType("dateByBackEnd");
            timeDefaultAttrPoJo.setDefaultValue(DateTimeUtil.getInt());
        }
        timeField.setDefaultAttr(timeDefaultAttrPoJo);
    }

    /**
     * 回/付款单关联新建坏账时格式化解释
     * @param xbbRefTypeEnum 业务类型 回款单or付款单
     * @param handlerExplainInLinkItemDTO 入参
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void formatSheetLinkAddBad(XbbRefTypeEnum xbbRefTypeEnum, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        FieldAttrEntity badTimeField = new FieldAttrEntity();
        FieldAttrEntity customerField = new FieldAttrEntity();
        FieldAttrEntity contractField = new FieldAttrEntity();
        FieldAttrEntity paymentField = new FieldAttrEntity();
        switch (xbbRefTypeEnum) {
            case PAY_SHEET:
                for(FieldAttrEntity fieldAttrEntity :explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.REAL_PAY_TIME.getAttr())) {
                        badTimeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_SUPPLIER.getAttr())) {
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_PURCHASE.getAttr())) {
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.PAY_PLAN.getAttr())) {
                        paymentField = fieldAttrEntity;
                    }
                }
                break;
            default:
                for(FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TIME.getAttr())) {
                        badTimeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CUSTOMER_ID.getAttr())){
                        customerField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CONTRACT.getAttr())){
                        contractField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT.getAttr())){
                        paymentField = fieldAttrEntity;
                    }
                }
                break;
        }
        //关联客户 关联合同默认值赋值
        Integer linkBusinessType = handlerExplainInLinkItemDTO.getLinkBusinessType();
        JSONArray customer;
        //关联应收款
        if(Objects.equals(linkBusinessType, XbbRefTypeEnum.PAYMENT.getCode())){
            customer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentEnum.CUSTOMER.getAttr(), new JSONArray());
            JSONArray contractArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentEnum.CONTRACT.getAttr(), new JSONArray());
            customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customer));
            contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
            paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
        }else if(Objects.equals(linkBusinessType, XbbRefTypeEnum.CONTRACT.getCode())){
            customer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, ContractEnum.LINK_CUSTOMER.getAttr(), new JSONArray());
            String contractId = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo();
            customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customer));
            contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, contractId));
        } else if(Objects.equals(linkBusinessType, XbbRefTypeEnum.PAY_PLAN.getCode())){
            customer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PayPlanEnum.LINK_SUPPLIER.getAttr(), new JSONArray());
            JSONArray contractArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PayPlanEnum.LINK_PURCHASE.getAttr(), new JSONArray());
            customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customer));
            contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractArr));
            paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
        }else if(Objects.equals(linkBusinessType, XbbRefTypeEnum.PURCHASE.getCode())){
            customer = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray());
            String contractNo = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo();
            customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customer));
            contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, contractNo));
        }
        // 日期
        DefaultAttrPoJo timeDefaultAttrPoJo = badTimeField.getDefaultAttr();
        if (Objects.isNull(timeDefaultAttrPoJo)) {
            timeDefaultAttrPoJo = new DefaultAttrPoJo();
        }
        timeDefaultAttrPoJo.setDefaultType("dateByBackEnd");
        timeDefaultAttrPoJo.setDefaultValue(DateTimeUtil.getInt());
        badTimeField.setDefaultAttr(timeDefaultAttrPoJo);
    }

    /**
     * 回/付款单关联新建红冲已核销、红冲预收/付款核销时格式化解释
     * @param xbbRefTypeEnum 业务类型 回款单or付款单
     * @param handlerExplainInLinkItemDTO 入参
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void formatLinkAddRed(XbbRefTypeEnum xbbRefTypeEnum, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long dataId = handlerExplainInLinkItemDTO.getLinkDataId();
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        FieldAttrEntity customerField = new FieldAttrEntity();
        FieldAttrEntity contractField = new FieldAttrEntity();
        FieldAttrEntity timeField = new FieldAttrEntity();
        FieldAttrEntity paymentField = new FieldAttrEntity();
        FieldAttrEntity fundAccountField = new FieldAttrEntity();
        FieldAttrEntity sheetField = new FieldAttrEntity();
        //支付方式
        FieldAttrEntity methodField = new FieldAttrEntity();
        JSONArray customerJsonArr;
        JSONArray contractJsonArr;
        Object timeDefaultValue;
        JSONArray paymentJsonArr;
        String fundAccountValue;
        String methodValue;
        switch (xbbRefTypeEnum) {
            case PAY_SHEET:
                for(FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_SUPPLIER.getAttr())) {
                        customerField = fieldAttrEntity;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.LINK_PURCHASE.getAttr())) {
                        contractField = fieldAttrEntity;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.REAL_PAY_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.PAY_PLAN.getAttr())) {
                        paymentField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.FUND_ACCOUNT.getAttr())) {
                        fundAccountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.ORIGIN_ID.getAttr())) {
                        sheetField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaySheetEnum.PAY_TYPE.getAttr())) {
                        methodField = fieldAttrEntity;
                    }
                }
                // 关联供应商，采购合同
                showFormatHelp.formatLinkBusiness4Show(linkFormData, PaySheetEnum.LINK_SUPPLIER.getAttr(), PaySheetEnum.SUPPLIER_LINK_TEXT.getAttr(), PaySheetEnum.LINK_SUPPLIER.getFieldType());
                showFormatHelp.formatLinkBusiness4Show(linkFormData, PaySheetEnum.LINK_PURCHASE.getAttr(), PaySheetEnum.PURCHASE_LINK_TEXT.getAttr(), PaySheetEnum.LINK_PURCHASE.getFieldType());
                customerJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaySheetEnum.LINK_SUPPLIER.getAttr(), new JSONArray());
                contractJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaySheetEnum.LINK_PURCHASE.getAttr(), new JSONArray());
                timeDefaultValue = FastJsonHelper.getLongOrDefaultFromFormData(linkFormData, PaySheetEnum.REAL_PAY_TIME.getAttr(), DateUtil.getNow());
                paymentJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaySheetEnum.PAY_PLAN.getAttr(), new JSONArray());
                fundAccountValue = FastJsonHelper.getStringFromFormData(linkFormData, PaySheetEnum.FUND_ACCOUNT.getAttr());
                methodValue = FastJsonHelper.getStringFromFormData(linkFormData, PaySheetEnum.PAY_TYPE.getAttr());
                break;
            default:
                for(FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CUSTOMER_ID.getAttr())) {
                        customerField = fieldAttrEntity;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.CONTRACT.getAttr())) {
                        contractField = fieldAttrEntity;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAYMENT.getAttr())) {
                        paymentField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.FUND_ACCOUNT.getAttr())) {
                        fundAccountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.RED_SHEET.getAttr())) {
                        sheetField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), PaymentSheetEnum.PAY_METHOD.getAttr())) {
                        methodField = fieldAttrEntity;
                    }
                }
                // 关联客户，合同
                showFormatHelp.formatLinkBusiness4Show(linkFormData, PaymentSheetEnum.CUSTOMER_ID.getAttr(), PaymentSheetEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), PaymentSheetEnum.CUSTOMER_ID.getFieldType());
                showFormatHelp.formatLinkBusiness4Show(linkFormData, PaymentSheetEnum.CONTRACT.getAttr(), PaymentSheetEnum.CONTRACT_LINK_TEXT.getAttr(), PaymentSheetEnum.CONTRACT.getFieldType());
                customerJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentSheetEnum.CUSTOMER_ID.getAttr(), new JSONArray());
                contractJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentSheetEnum.CONTRACT.getAttr(), new JSONArray());
                timeDefaultValue = FastJsonHelper.getLongOrDefaultFromFormData(linkFormData, PaymentSheetEnum.PAYMENT_TIME.getAttr(), DateUtil.getNow());
                paymentJsonArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, PaymentSheetEnum.PAYMENT.getAttr(), new JSONArray());
                fundAccountValue = FastJsonHelper.getStringFromFormData(linkFormData, PaymentSheetEnum.FUND_ACCOUNT.getAttr());
                methodValue = FastJsonHelper.getStringFromFormData(linkFormData, PaymentSheetEnum.PAY_METHOD.getAttr());
                break;
        }
        customerField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(customerJsonArr));
        contractField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(contractJsonArr));
        // 红冲日期
        DefaultAttrPoJo timeDefaultAttrPoJo = timeField.getDefaultAttr();
        if (Objects.isNull(timeDefaultAttrPoJo)) {
            timeDefaultAttrPoJo = new DefaultAttrPoJo();
        }
        timeDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        timeDefaultAttrPoJo.setDefaultValue(timeDefaultValue);
        timeField.setDefaultAttr(timeDefaultAttrPoJo);
        paymentField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(paymentJsonArr));
        commonHelp.handleLinkAdd4Combo(fundAccountField, fundAccountValue);
        sheetField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(dataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
        commonHelp.handleLinkAdd4Combo(methodField, methodValue);
        commonHelp.handleLinkAdd4Combo(methodField, methodValue);
    }

    /**
     * 其他收入单、其他支出单关联新建红冲已收款、已付款时格式化解释
     * @param xbbRefTypeEnum 业务类型 其他收入单、其他支出单
     * @param handlerExplainInLinkItemDTO 入参
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void formatOtherLinkAddRed(XbbRefTypeEnum xbbRefTypeEnum, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long dataId = handlerExplainInLinkItemDTO.getLinkDataId();
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        FieldAttrEntity amountField = new FieldAttrEntity();
        FieldAttrEntity timeField = new FieldAttrEntity();
        FieldAttrEntity fundAccountField = new FieldAttrEntity();
        FieldAttrEntity sheetField = new FieldAttrEntity();
        //支付方式
        FieldAttrEntity methodField = new FieldAttrEntity();
        Object timeDefaultValue;
        String fundAccountValue;
        String methodValue;
        double leftAmount;
        switch (xbbRefTypeEnum) {
            case OTHER_EXPENSE:
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), OtherExpenseEnum.AMOUNT.getAttr())) {
                        amountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherExpenseEnum.EXPENSE_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherExpenseEnum.FUND_ACCOUNT.getAttr())) {
                        fundAccountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherExpenseEnum.ORIGIN_ID.getAttr())) {
                        sheetField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherExpenseEnum.PAY_METHOD.getAttr())) {
                        methodField = fieldAttrEntity;
                    }
                }
                //处理红冲金额
                double originAmout = linkFormData.getDoubleValue(OtherExpenseEnum.AMOUNT.getAttr());
                //原单已红冲金额
                double redAmount = saasOtherExpenseHelp.sumRedAmountBySheet(corpid, dataId);
                //剩余总的可红冲金额 = 关联原支出单总金额 - 原单总的已红冲金额(由于红冲金额为负数，因此此处用add)
                leftAmount = Arith.add(originAmout, redAmount);
                //处理日期等
                timeDefaultValue = FastJsonHelper.getLongOrDefaultFromFormData(linkFormData, OtherExpenseEnum.EXPENSE_TIME.getAttr(), DateUtil.getNow());
                fundAccountValue = FastJsonHelper.getStringFromFormData(linkFormData, OtherExpenseEnum.FUND_ACCOUNT.getAttr());
                methodValue = FastJsonHelper.getStringFromFormData(linkFormData, OtherExpenseEnum.PAY_METHOD.getAttr());
                break;
            default:
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), OtherIncomeEnum.AMOUNT.getAttr())) {
                        amountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherIncomeEnum.INCOME_TIME.getAttr())) {
                        timeField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherIncomeEnum.FUND_ACCOUNT.getAttr())) {
                        fundAccountField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherIncomeEnum.ORIGIN_ID.getAttr())) {
                        sheetField = fieldAttrEntity;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(), OtherIncomeEnum.PAY_METHOD.getAttr())) {
                        methodField = fieldAttrEntity;
                    }
                }
                //处理红冲金额
                originAmout = linkFormData.getDoubleValue(OtherIncomeEnum.AMOUNT.getAttr());
                //原单已红冲金额
                redAmount = saasOtherIncomeHelp.sumRedAmountBySheet(corpid, dataId);
                //剩余总的可红冲金额 = 关联原收入单总金额 - 原单总的已红冲金额(由于红冲金额为负数，因此此处用add)
                leftAmount = Arith.add(originAmout, redAmount);
                //处理日期等
                timeDefaultValue = FastJsonHelper.getLongOrDefaultFromFormData(linkFormData, OtherIncomeEnum.INCOME_TIME.getAttr(), DateUtil.getNow());
                fundAccountValue = FastJsonHelper.getStringFromFormData(linkFormData, OtherIncomeEnum.FUND_ACCOUNT.getAttr());
                methodValue = FastJsonHelper.getStringFromFormData(linkFormData, OtherIncomeEnum.PAY_METHOD.getAttr());
                break;
        }
        DefaultAttrPoJo amountAttrPojo = new DefaultAttrPoJo();
        amountAttrPojo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        amountAttrPojo.setDefaultValue(leftAmount);
        amountField.setDefaultAttr(amountAttrPojo);
        // 红冲日期
        DefaultAttrPoJo timeDefaultAttrPoJo = timeField.getDefaultAttr();
        if (Objects.isNull(timeDefaultAttrPoJo)) {
            timeDefaultAttrPoJo = new DefaultAttrPoJo();
        }
        timeDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        timeDefaultAttrPoJo.setDefaultValue(timeDefaultValue);
        timeField.setDefaultAttr(timeDefaultAttrPoJo);
        commonHelp.handleLinkAdd4Combo(fundAccountField, fundAccountValue);
        sheetField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(dataId, handlerExplainInLinkItemDTO.getPaasFormDataEntityExt().getSerialNo()));
        commonHelp.handleLinkAdd4Combo(methodField, methodValue);
    }

    /**
     * 新建时saas特殊返回字段，放在一个对象中
     *
     * @param formDataAddGetVO
     * @author chaoxiong.lei
     * @Date 15:26 2019/2/18
     * @since
     * @return void
     **/
    public void formatSaasAttrToReturn(FormDataAddGetVO formDataAddGetVO, FormDataAddGetDTO formDataAddGetDTO) throws XbbException {
        Integer businessType = formDataAddGetDTO.getBusinessType();
        if (formDataAddGetVO == null || businessType == null) {
            return;
        }
        RedundantTemplateTypeEnum templateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        JSONObject saasReturnObj = new JSONObject();
        switch (templateTypeEnum) {
            case PRODUCT:
                // TODO 是否启用进销存
                Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), formDataAddGetDTO.getSaasMark(), formDataAddGetDTO.getCorpid());
//
                if (!isJxcUse){
                    List<FieldAttrEntity> explainList = formDataAddGetVO.getExplainList();
                    for (FieldAttrEntity fieldAttrEntity : explainList) {
                        if (Objects.equals(ProductEnum.SUPPLIER.getAttr(), fieldAttrEntity.getAttr())){
                            fieldAttrEntity.setVisible(0);
                        }
                    }
                }
                saasReturnObj.put("isJxcUse", isJxcUse);
                formDataAddGetVO.setSaasObj(saasReturnObj);
                break;
            default:
                break;
        }
    }

    /**
     * 从数据库中实时获取关联产品的字段解释
     *
     * @param corpid 公司id
     * @param businessType 业务
     * @param listGroupId 分组
     * @author chaoxiong.lei
     * @date 17:28 2019/3/2
     * @since v1.0
     **/
    public RelativeProductExplainVO getRelativeProductExplainsFromDB(String corpid, Integer businessType, Long listGroupId) throws XbbException {
        RelativeProductExplainVO relativeProductExplainVO = new RelativeProductExplainVO();
        if (corpid == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }

        if (Objects.equals(businessType, XbbRefTypeEnum.STOCK_SEARCH.getCode())) {
            if (Objects.equals(listGroupId, ListGroupEnum.WARNING_SEARCH.getCode().longValue())) {
                businessType = XbbRefTypeEnum.WARNING_SEARCH.getCode();
            } else if (Objects.equals(listGroupId, ListGroupEnum.GUARANTEE_SEARCH.getCode().longValue())) {
                businessType = XbbRefTypeEnum.GUARANTEE_SEARCH.getCode();
            }
        }
        // 拼装解释
        List<SubOptionTableHeadEnum> optionTableHeadEnums = OptionTableHeadEnum.getListByBusinessType(businessType);
        // 用于存放当前启用的产品模板解释的map
        Map<String, FieldAttrEntity> nowProductExplainMap = null;
        if (Objects.equals(optionTableHeadEnums, OptionTableHeadEnum.STOCK_SEARCH.getList())
                || Objects.equals(optionTableHeadEnums, OptionTableHeadEnum.WARNING_SEARCH.getList()) || Objects.equals(optionTableHeadEnums, OptionTableHeadEnum.PRODUCT.getList()) ) {
            nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }
        // 用于存放当前启用的产品库存模板解释的map
        Map<String, FieldAttrEntity> nowStockProductExplainMap = null;
        if (Objects.equals(optionTableHeadEnums, OptionTableHeadEnum.GUARANTEE_SEARCH.getList())) {
            nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (nowProductExplainMap != null) {
            // 获取当前启用的产品字段解释
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("saasMark", 1);
            param.put("businessType", XbbRefTypeEnum.PRODUCT.getCode());
            List<PaasFormExplainEntity> formExplainList = paasFormExplainModel.list(param);
            if (!formExplainList.isEmpty()) {
                PaasFormExplainEntity paasFormExplainEntity = formExplainList.get(0);
                List<FieldAttrEntity> nowProductExplainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity entity : nowProductExplainList) {
                    nowProductExplainMap.put(entity.getSaasAttr(), entity);
                }
            }
        }

        if (nowProductExplainMap != null && nowStockProductExplainMap != null) {
            // 获取当前启用的库存产品字段解释
            param.clear();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("saasMark", 1);
            param.put("businessType", XbbRefTypeEnum.STOCK_PRODUCT.getCode());
            List<PaasFormExplainEntity> stockProductExplainList = paasFormExplainModel.list(param);
            if (!stockProductExplainList.isEmpty()) {
                PaasFormExplainEntity paasFormExplainEntity = stockProductExplainList.get(0);
                List<FieldAttrEntity> nowStockProductExplainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity entity : nowStockProductExplainList) {
                    Integer isRedundant = entity.getIsRedundant();
                    if (Objects.equals(isRedundant, 0)) {
                        // 系统字段，key为saasAttr
                        nowProductExplainMap.put(entity.getSaasAttr(), entity);
                    } else {
                        // 自定义字段，key为attr
                        nowStockProductExplainMap.put(entity.getAttr(), entity);
                    }
                }
            }
        }

        relativeProductExplainVO.setNowProductExplainMap(nowProductExplainMap);
        relativeProductExplainVO.setNowStockProductExplainMap(nowStockProductExplainMap);
        return relativeProductExplainVO;
    }

    public void handleFormEntity(PaasFormEntityExt paasFormEntityExt, Integer saasMark, Integer businessType) {
        FormUtil.handleFormEntity(paasFormEntityExt, saasMark, businessType);
    }

    /**
     * 关联新建时为资金账户置入默认值：选中下拉选项的第一个
     * @param fundAccountField 资金账户字段实体
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void handleLinkAdd4AccountDefault(FieldAttrEntity fundAccountField) {
        List<ItemPoJo> fundAccountItemList = fundAccountField.getItems();
        if (fundAccountItemList != null && fundAccountItemList.size() > 0) {
            for (ItemPoJo itemPojo : fundAccountItemList) {
                if (!Objects.equals(itemPojo.getShowType(), ShowTypeEnum.EXCLUDE_NEW.getCode())) {
                    //第一个启用的置为选中即可
                    itemPojo.setChecked(true);
                    break;
                }
            }
        }
    }

    /**
     * 合并回/付款校验
     * @param redundantTemplateTypeEnum 业务类型
     * @param paasFormDataEntityExts 实体集合
     * @throws XbbException error
     * @author zhouwq
     * @date 2019/12/10 16:26
     * @update 2020/3/4 by zcp 从PaymentSheetServiceImpl移入，且改造支持合并付款校验
     */
    private void verifySheetData(RedundantTemplateTypeEnum redundantTemplateTypeEnum, List<PaasFormDataEntityExt> paasFormDataEntityExts) throws XbbException {
        Long lastCustomerId = null;
        switch (redundantTemplateTypeEnum) {
            case PAYMENT:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
                    JSONObject dataList = paasFormDataEntityExt.getData();
                    String paymentStatus = FastJsonHelper.getStringFromFormData(dataList, PaymentEnum.STATUS.getAttr());
                    if (PaymentStatusEnum.noMerge(paymentStatus)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PAYMENT_BAD_STATUS);
                    }
                    JSONArray customerArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PaymentEnum.CUSTOMER.getAttr(), new JSONArray());
                    if (customerArr.isEmpty()) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_LINK_CUSTOMER);
                    }
                    Long customerId = customerArr.getJSONObject(BasicConstant.ZERO).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                    if (Objects.isNull(customerId) || Objects.equals(customerId, 0L)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_LINK_CUSTOMER);
                    }
                    if (Objects.nonNull(lastCustomerId) && !Objects.equals(lastCustomerId, customerId)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PAYMENT_PAYMENT_SHEET_MUST_SAME_CUSTOMER);
                    }
                    lastCustomerId = customerId;
                    Double unAmount = getDoubleOrDefaultFromFormData(dataList, PaymentEnum.UN_AMOUNT.getAttr(), 0D);
                    if(unAmount <= 0D) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_PAYMENT_SHEET_AMOUNT_MERGE, XbbRefTypeEnum.PAYMENT.getName());
                    }
                }
                break;
            case CONTRACT:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
                    JSONObject dataList = paasFormDataEntityExt.getData();
                    JSONArray customerArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, ContractEnum.LINK_CUSTOMER.getAttr(), new JSONArray());
                    if (customerArr.isEmpty()) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_LINK_CUSTOMER);
                    }
                    Long customerId = customerArr.getJSONObject(BasicConstant.ZERO).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                    if (Objects.isNull(customerId) || Objects.equals(customerId, 0L)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_LINK_CUSTOMER);
                    }
                    if (Objects.nonNull(lastCustomerId) && !Objects.equals(lastCustomerId, customerId)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_PAYMENT_SHEET_MUST_SAME_CUSTOMER);
                    }
                    lastCustomerId = customerId;
                    Double unAmount = getDoubleOrDefaultFromFormData(dataList, ContractEnum.UN_FINISH_AMOUNT.getAttr(), 0D);
                    if(unAmount <= 0D) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.CONTRACT_PAYMENT_SHEET_AMOUNT_MERGE, I18nMessageUtil.getMessage(CommonConstant.CONTRACT));
                    }
                }
                break;
            case PAY_PLAN:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
                    JSONObject dataList = paasFormDataEntityExt.getData();
                    String payPlanStatus = FastJsonHelper.getStringFromFormData(dataList, PayPlanEnum.STATUS.getAttr());
                    if (Objects.equals(PayPlanStatusEnum.getBad(payPlanStatus), BasicConstant.ONE)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PAY_PLAN_BAD_STATUS);
                    }
                    JSONArray supplierArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PayPlanEnum.LINK_SUPPLIER.getAttr(), new JSONArray());
                    if (supplierArr.isEmpty()) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_LINK_SUPPLIER);
                    }
                    Long supplierId = supplierArr.getJSONObject(BasicConstant.ZERO).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                    if (Objects.isNull(supplierId) || Objects.equals(supplierId, 0L)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_LINK_SUPPLIER);
                    }
                    if (Objects.nonNull(lastCustomerId) && !Objects.equals(lastCustomerId, supplierId)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PAY_PLAN_PAY_SHEET_MUST_SAME_SUPPLIER);
                    }
                    lastCustomerId = supplierId;
                    Double unAmount = getDoubleOrDefaultFromFormData(dataList, PayPlanEnum.UN_AMOUNT.getAttr(), 0D);
                    if(unAmount <= 0D) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_PAY_SHEET_AMOUNT_MERGE, XbbRefTypeEnum.PAY_PLAN.getName());
                    }
                }
                break;
            case PURCHASE:
                for(PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
                    JSONObject dataList = paasFormDataEntityExt.getData();
                    JSONArray supplierArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray());
                    if (supplierArr.isEmpty()) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_LINK_SUPPLIER);
                    }
                    Long supplierId = supplierArr.getJSONObject(BasicConstant.ZERO).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                    if (Objects.isNull(supplierId) || Objects.equals(supplierId, 0L)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_LINK_SUPPLIER);
                    }
                    if (Objects.nonNull(lastCustomerId) && !Objects.equals(lastCustomerId, supplierId)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_PAY_SHEET_MUST_SAME_SUPPLIER);
                    }
                    lastCustomerId = supplierId;
                    Double unAmount = getDoubleOrDefaultFromFormData(dataList, PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), 0D);
                    if(unAmount <= 0D) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.PURCHASE_PAY_SHEET_AMOUNT_MERGE, XbbRefTypeEnum.PURCHASE.getName());
                    }
                }
                break;
            default:
                break;
        }
    }

    /**
     * 处理关联业务（去重），把其置入相应对象
     * @param linkArr 关联业务数组
     * @param linkIds 关联业务id数组
     * @param linkFormData 关联对象
     * @param linkAttr 关联字段attr
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private void formatSheetLink(JSONArray linkArr, List<Long> linkIds, JSONObject linkFormData, String linkAttr) throws XbbException {
        JSONArray link = FastJsonHelper.getJsonArrOrDefaultFromFormData(linkFormData, linkAttr, new JSONArray());
        //去重
        for (Object obj : link) {
            JSONObject linkObj = (JSONObject) obj;
            Long linkId = linkObj.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
            if (!linkIds.contains(linkId)) {
                linkArr.add(linkObj);
                linkIds.add(linkId);
            }
        }
    }
}
